﻿/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A
 * copy of the license can be found at http://go.microsoft.com/fwlink/?LinkID=131993. If
 * you cannot locate the Microsoft Public License, please send an email to
 * mixon@microsoft.com. By using this source code in any fashion, you are agreeing to
 * be bound by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MIXOnline.Descry
{
    public partial class TreeMapControl : UserControl
    {
        Dictionary<string, TreeMapPanelItem> dict = new Dictionary<string, TreeMapPanelItem>();

        Stack<TreeMapPanel> WorkingTreeMapPanel = new Stack<TreeMapPanel>();

        public TreeMapControl()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Wipes all of the child nodes
        /// </summary>
        public void ClearTreeMap()
        {
            treeMapPanel.Children.Clear();

            dict.Clear();

            WorkingTreeMapPanel.Push(treeMapPanel);

        }

        /// <summary>
        /// Gets a list of all of the leaf node items (currently doesn't do depth-first traversal)
        /// </summary>
        /// <returns>A list of TreeMapPanelItems</returns>
        public IEnumerable<TreeMapPanelItem> LeafPanels()
        {
            foreach (UIElement e in treeMapPanel.Children)
            {
                if (e is TreeMapPanelItem) yield return (TreeMapPanelItem)e;
            }
        }

        /// <summary>
        /// Clears and loads the TreeMapControl from a list of items
        /// </summary>
        /// <param name="items">A list or array of TreeMapItems</param>
        public void LoadTreeMap(IEnumerable<TreeMapItem> items)
        {
            TreeMapItem item = new TreeMapItem
            {
                Label = "root",
                Size = 0,
                Children = items.ToList()
            };

            LoadTreeMap(item);
        }

        /// <summary>
        /// Clears and loads the TreeMapControl from a single root item which has children, representing a tree
        /// </summary>
        /// <param name="item">A TreeMapItem which has one or more children</param>
        public void LoadTreeMap(TreeMapItem item)
        {
            ClearTreeMap();
            LoadTreeMap(item, false);
        }

        /// <summary>
        /// Internal utility function that recursively walks the TreeMapItem hierarchy and builds the Tree Map
        /// </summary>
        /// <param name="item">The root TreeMapItem for this call</param>
        /// <param name="IsLastItem">Boolean indicating whether this is the bottom level of recursion</param>
        private void LoadTreeMap(TreeMapItem item, bool IsLastItem)
        {
            List<TreeMapItem> children = item.Children;
            int childCount = children.Count();

            string name = item.Label;

            long size = item.Size;

            if (childCount == 0)
            {
                ConstructorInfo ci = item.PanelItemType.GetConstructor(new Type[] { typeof(TreeMapItem) });
                TreeMapPanelItem tmi = (TreeMapPanelItem)ci.Invoke(new object[] { item });

                tmi.Label = name; 
                tmi.Background = new SolidColorBrush(item.Color);

                TreeMapPanel.SetArea(tmi, size);

                TreeMapPanel t = WorkingTreeMapPanel.Peek();

                t.Children.Add(tmi);
            }
            else // if there are subitems create a TreeMapPanel
            {
                if (size != 0) // don't add a TreeMapPanel if size is zero
                {
                    TreeMapPanel tmp = new TreeMapPanel();
                    TreeMapPanel.SetArea(tmp, size);
                    tmp.Label = name;
                    tmp.Color = item.Color;

                    TreeMapPanel t = WorkingTreeMapPanel.Peek();
                    t.Children.Add(tmp);

                    WorkingTreeMapPanel.Push(tmp); // make this the working TreeMapPanel.
                }

                for (int count = 0; count < children.Count(); count++)
                {
                    LoadTreeMap(children.ElementAt(count), count == children.Count() - 1);
                }
            }
            if (IsLastItem)
                WorkingTreeMapPanel.Pop();

        }

    }
}